package com.ybear.ybcomponent.widget.linkage.effector.base

import android.animation.Animator
import android.animation.ValueAnimator
import android.content.Context
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.view.animation.DecelerateInterpolator
import com.ybear.ybcomponent.widget.linkage.enums.ViewLinkage

/**
 * @Author MiWi
 * @Date 2025年2月13日
 * @Description Linkage - 基类效果器
 */
abstract class CoreEffector {
    open val Float.dp2Px: Float
        get() {
            if( density == 0F ) updateDensity()
            return this * density + 0.5F
        }

    open val Float.px2Dp: Float
        get() {
            if( density == 0F ) updateDensity()
            return this / density + 0.5F
        }

    open val Int.dp2Px: Int
        get() = this.toFloat().dp2Px.toInt()

    open val Int.px2Dp: Int
        get() = this.toFloat().px2Dp.toInt()

    private var density: Float = 0F

    lateinit var context: Context
    lateinit var parent: ViewGroup
    lateinit var motionEvent: MotionEvent
    lateinit var childView: View

    // 记录触摸按下时的 X 坐标
    open var downScrollX = 0F
        protected set
    // 记录触摸按下时的 Y 坐标
    open var downScrollY = 0F
        protected set
    open var isFingerDown = false
        protected set
    // 起始距离
    open var startOffset = 0F
        protected set
    // 终止距离
    open var endOffset = 0F
        protected set
    var isAnimRunning = false
        private set

    fun viewWidth() : Int {
        val w = childView.width
        if( w > 0 ) return w
        val mw = childView.measuredWidth
        if( mw > 0 ) return mw
        childView.measure( 0, 0 )
        return childView.measuredWidth
    }

    fun viewHeight() : Int {
        val h = childView.height
        if( h > 0 ) return h
        val mh = childView.measuredHeight
        if( mh > 0 ) return mh
        childView.measure( 0, 0 )
        return childView.measuredHeight
    }

    abstract fun onViewLinkage() : ViewLinkage

    fun bindParent(parent: ViewGroup) : CoreEffector {
        this.context = parent.context
        this.parent = parent
        return this
    }

    fun bindMotionEvent(motionEvent: MotionEvent) : CoreEffector {
        this.motionEvent = motionEvent
        return this
    }

    fun bindChildView(childView: View) : CoreEffector {
        this.childView = childView
        return this
    }

    fun buildEffector(startOffset: Float, endOffset: Float) : Boolean {
        this.startOffset = startOffset
        this.endOffset = endOffset
        when( motionEvent.action ) {
            MotionEvent.ACTION_DOWN -> {
                updateDensity()
                isFingerDown = true
                downScrollX = motionEvent.x         // 记录初始 X 坐标
                downScrollY = motionEvent.y         // 记录初始 Y 坐标
            }
            MotionEvent.ACTION_UP,
            MotionEvent.ACTION_CANCEL -> {
                isFingerDown = false
            }
        }
        return onEffector( startOffset, endOffset )
    }

    abstract fun onEffector(startOffset: Float, endOffset: Float) : Boolean

    abstract fun restoreEffector(animator: Boolean)

    /**
     * 创建动画
     */
    @Suppress("UNCHECKED_CAST")
    open fun <T> createNumberAnimator(
        from: T,
        to: T,
        duration: Long,
        update: (T) -> Unit
    ): ValueAnimator {
        val animator = when( from ) {
            is Int -> ValueAnimator.ofInt( from, to as Int )
            is Float -> ValueAnimator.ofFloat( from, to as Float )
            else -> null
        } ?: throw NullPointerException( "Unsupported type" )
        animator.duration = duration
        animator.interpolator = DecelerateInterpolator()
        animator.addUpdateListener { valueAnimator ->
            update.invoke( valueAnimator.animatedValue as T )
        }
        animator.addListener(object : Animator.AnimatorListener {
            override fun onAnimationStart(animation: Animator) { isAnimRunning = true }
            override fun onAnimationEnd(animation: Animator) { isAnimRunning = false }
            override fun onAnimationCancel(animation: Animator) { isAnimRunning = false }
            override fun onAnimationRepeat(animation: Animator) { }
        })
        return animator
    }

    private fun updateDensity() {
        density = context.resources.displayMetrics.density
    }
}